﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
using System.Xml.Serialization;
using System.Xml;

namespace Rung.Common
{
    public static class SerializeHelper
    {
        #region binary serialize
        public static void Serialize(object o, string fullFileName)
        {
            // 保证路径存在
            FileInfo fi = new FileInfo(fullFileName);
            if (!Directory.Exists(fi.DirectoryName))
            {
                Directory.CreateDirectory(fi.DirectoryName);
            }

            // 保存
            using (FileStream fileStream = new FileStream(fullFileName, FileMode.Create))
            {
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(fileStream, o);
                fileStream.Close();
            }
        }


        public static byte[] Serialize(object o)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(ms, o);

                ms.Seek(0, SeekOrigin.Begin);
                byte[] result = new byte[ms.Length];
                ms.Write(result, 0, (int)ms.Length);

                return result;
            }
        }

        public static T DeSerialize<T>(string fullFileName, SerializationBinder binder) where T : class
        {
            using (FileStream fileStream = new FileStream(fullFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                BinaryFormatter b = new BinaryFormatter();
                if (null != binder) b.Binder = binder;

                try
                {
                    return b.Deserialize(fileStream) as T;
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
        }

        public static T DeSerialize<T>(string fullFileName) where T : class
        {
            return DeSerialize<T>(fullFileName, null);
        } 
        #endregion

        #region xml serialize
        /// <summary>
        /// 将指定对象序列化，并返回序列化后的 XML 结果。
        /// </summary>
        public static string XmlSerialize<T>(T o)
        {
            using (StringWriter sw = new StringWriter())
            {
                XmlSerializer xz = new XmlSerializer(o.GetType());
                xz.Serialize(sw, o);
                return sw.ToString();
            }
        }

        /// <summary>
        /// 将指定对象序列化，并保存序列化后的 XML 结果到指定位置。
        /// </summary>
        public static void XmlSerialize<T>(T o, string fullFileName, params Type[] types)
        {
            XmlSerializer xs = new XmlSerializer(o.GetType(), types);
            using (Stream stream = new FileStream(fullFileName, FileMode.Create, FileAccess.Write, FileShare.Read))
            {
                xs.Serialize(stream, o);
                stream.Close();
            }
        }

        public static T XmlDeserialize<T>(string fullFileName) where T : class
        {
            XmlSerializer xs = new XmlSerializer(typeof(T));
            using (Stream stream = new FileStream(fullFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                return xs.Deserialize(stream) as T;
            }
        } 
        #endregion

        #region xml serialize helper
        public static void WriteXmlStringList(XmlWriter writer, List<string> list, string elementName)
        {
            writer.WriteStartElement(elementName);
            foreach (var item in list)
            {
                writer.WriteElementString("string", item);
            }
            writer.WriteEndElement();
        }

        public static List<string> ReadXmlStringList(XmlReader reader, string elementName)
        {
            if (reader.IsStartElement(elementName))
                reader.ReadStartElement(elementName);
            else
                throw (new XmlException(string.Format("待读取的Xml元素不是 {0}。", elementName)));

            List<string> result = new List<string>();
            if (!reader.IsEmptyElement)
            {
                XmlReader r2 = reader.ReadSubtree();
                while (!r2.EOF)
                    result.Add(r2.ReadElementString("string"));
            }

            return result;
        }
        #endregion
    }
}
